Skip to content

feat(project): pre-render / post-render project scripts (bd-w348iu63) - #448

Merged
cscheid merged 1 commit into
mainfrom
feature/bd-w348iu63-pre-post-render-scripts
Jul 31, 2026
Merged

feat(project): pre-render / post-render project scripts (bd-w348iu63)#448
cscheid merged 1 commit into
mainfrom
feature/bd-w348iu63-pre-post-render-scripts

Conversation

@cscheid

@cscheid cscheid commented Jul 31, 2026

Copy link
Copy Markdown
Member

Ports Quarto 1's project.pre-render / project.post-render script support to Q2, for all project types. Strand: bd-w348iu63; plan: claude-notes/plans/2026-07-29-pre-post-render-scripts.md.

What

project:
  type: website
  pre-render: prepare.py          # string or list; full command lines OK
  post-render:
    - cleanup.R
    - python3 tools/notify.py --label "site build"
  • Runner (quarto-core::project::render_scripts): string-or-list config extraction with YAML source locations; Q1-parity quote-aware command-line parser; dispatch on the first token's extension (.pyQUARTO_PYTHON/python3, .r → knitr find_rscript, .ts/.jsQUARTO_NODE/node, anything else direct-exec resolved against the project root); the QUARTO_PROJECT_* env contract; QUARTO_USE_FILE_FOR_PROJECT_{INPUT,OUTPUT}_FILES escape hatch (Q1 #10828). Exec half is native-gated, extraction compiles on WASM.
  • q2 render: discover → pre-render → re-discover (script-created inputs render in the same pass) → mutation guard (project.type / project.output-dir frozen, Q1-compatible) → pipeline → post-render with env computed fresh from actual outputs (fixes Q1's stale-env wart). New --no-render-scripts flag.
  • q2 publish: same bracket; post-render runs before the sidecar walk so script-added output files get published.
  • q2 preview: pre-render scripts run once at boot (before eager captures), never re-run — a decided deviation from Q1's every-re-render behavior; failures keep the preview serving. No post-render in preview.
  • Hub/WASM: scripts can't run in the browser; a one-time Q-5-12 warning is surfaced through the existing diagnostics channel.
  • Diagnostics: Q-5-8 (script failed, ariadne snippet pointing at the exact pre-render: YAML scalar + exit code), Q-5-9 (forbidden mutation), Q-5-10 (launch failure), Q-5-11 (pre_render underscore-typo warning), Q-5-12 (unsupported environment).
  • Docs: docs/guides/projects/scripts.qmd — config keys, env-var table, dispatch rules, preview behavior, Q1 differences.

Q1 → Q2 differences (deliberate)

Area Q1 Q2
.ts/.js bundled Deno + import maps node from PATH (QUARTO_NODE)
.lua run as pandoc Lua filter no special case
Post-render env stale (computed pre-render) fresh from actual outputs
Script failure empty Error sourced diagnostic + exit code
Preview cadence scripts on every re-render pre-render at boot only
Skip flag none --no-render-scripts

Testing

TDD (all new tests verified failing before implementation):

  • 14 CLI e2e tests (crates/quarto/tests/integration/render_scripts_cli.rs) driving the real q2 binary: script-created inputs, env contract full vs subset, failure abort semantics, mutation guards, ordering, quoted args, escape hatch, --no-render-scripts, direct-exec (#[cfg(unix)] sh / #[cfg(windows)] bat), typo warning. Python fixtures skip gracefully when no interpreter is present.
  • 17 unit tests (parser, extraction, typo guard, mutation guard, catalog registration).
  • 1 preview boot test (runs once at boot, does not re-run on file change).

cargo nextest run --workspace: 10806 passed. cargo xtask verify (full, incl. WASM leg): green. cargo xtask lint: clean. End-to-end verified manually per CLAUDE.md (fixture output inspected; recorded in the plan doc).

🤖 Generated with Claude Code

Port Quarto 1's project.pre-render / project.post-render script
support to Q2, for all project types:

- quarto-core::project::render_scripts: config extraction (string or
  list, with YAML source locations), Q1-parity quote-aware command
  parser, extension dispatch (.py -> QUARTO_PYTHON/python3, .r ->
  knitr find_rscript, .ts/.js -> QUARTO_NODE/node, else direct exec
  resolved against the project root), the QUARTO_PROJECT_* env
  contract, and the QUARTO_USE_FILE_FOR_PROJECT_{INPUT,OUTPUT}_FILES
  escape hatch. Exec half native-gated; extraction compiles on WASM.
- q2 render: discover -> pre-render -> re-discover -> mutation guard
  (project.type / project.output-dir frozen, Q1-compatible) ->
  pipeline -> post-render with env computed fresh from the actual
  outputs (fixes Q1's stale-env wart). New --no-render-scripts flag.
- q2 publish: same bracket; post-render runs before the sidecar walk
  so script-added output files get published.
- q2 preview: pre-render scripts run once at boot (before eager
  captures), never re-run; failure keeps the preview serving.
- Hub/WASM: one-time Q-5-12 warning when scripts are configured.
- Error catalog: Q-5-8 script failed, Q-5-9 forbidden mutation,
  Q-5-10 launch failure, Q-5-11 underscore-typo warning, Q-5-12
  unsupported environment.
- Docs: docs/guides/projects/scripts.qmd (config keys, env table,
  dispatch rules, preview deviations, Q1 differences).

Tests (written first, verified red): 14 CLI e2e tests
(render_scripts_cli), 17 unit tests (render_scripts), 1 preview boot
test (render_scripts_boot). Workspace suite 10806 green; full
cargo xtask verify green.

Plan: claude-notes/plans/2026-07-29-pre-post-render-scripts.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Jul 31, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@cscheid
cscheid merged commit 4f3d073 into main Jul 31, 2026
8 checks passed
@cscheid
cscheid deleted the feature/bd-w348iu63-pre-post-render-scripts branch July 31, 2026 21:32
cscheid added a commit that referenced this pull request Jul 31, 2026
…16-1..6)

Both sides appended entries at the file tail; no key or subsystem
collisions. Resolved per snapshot-of-truth policy for generated-ish
files: took main's version and re-added the Q-16 extension-subsystem
entries. Workspace suite green post-merge (10,853 tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants